sysroot: Detect early on when /boot is on vfat
authorColin Walters <walters@verbum.org>
Sun, 6 Apr 2025 21:24:26 +0000 (17:24 -0400)
committerColin Walters <walters@verbum.org>
Wed, 30 Apr 2025 19:29:50 +0000 (15:29 -0400)
We do want to support this (as part of supporing the
Boot Loader Spec) but because we use symlinks in `/boot`,
can't yet.

Error out very early on consistently if we detect
vfat for /boot, but also add a member variable to keep track
of this in preparation for supporting it.

Signed-off-by: Colin Walters <walters@verbum.org>
src/libostree/ostree-sysroot-deploy.c
src/libostree/ostree-sysroot-private.h
src/libostree/ostree-sysroot.c
tests/kolainst/nondestructive/itest-alt-sysroot.sh [new file with mode: 0755]

index 49168d4f170395aa313cf3cc0ba1dd180c7cd784..6803d1d0771a972ede8c6957022ff87f198074c8 100644 (file)
@@ -2216,8 +2216,9 @@ swap_bootloader (OstreeSysroot *sysroot, OstreeBootloader *bootloader, int curre
 
   if (!_ostree_sysroot_ensure_boot_fd (sysroot, error))
     return FALSE;
-
   g_assert_cmpint (sysroot->boot_fd, !=, -1);
+  // We use symlinks here.
+  g_assert (!sysroot->boot_is_vfat);
 
   /* The symlink was already written, and we used syncfs() to ensure
    * its data is in place.  Renaming now should give us atomic semantics;
index ac5d271c516e460c94e72c1860aaf49e89c21615..9a6566d5ad0cabd391c60f150e988efc30a85811 100644 (file)
@@ -70,6 +70,9 @@ struct OstreeSysroot
   // File descriptor for the boot partition. Should be initialized on demand internally
   // by a public API eventually invoking `_ostree_sysroot_ensure_boot_fd()`.
   int boot_fd;
+  // Set if the /boot filesystem is VFAT.
+  // Only initialized if boot_fd is set.
+  gboolean boot_is_vfat;
   // Lock for this sysroot.
   GLnxLockFile lock;
 
index 3e237c398a563c9679a1b1b720cb1a25449db5bb..e45a71f689398ea3bac3988cec47d82403ca349d 100644 (file)
 
 #include "otutil.h"
 #include <err.h>
+#include <linux/magic.h>
 #include <sys/file.h>
 #include <sys/mount.h>
+#include <sys/vfs.h>
 #include <sys/wait.h>
 
 #include "ostree-bootloader-aboot.h"
@@ -338,6 +340,19 @@ ensure_sysroot_fd (OstreeSysroot *self, GError **error)
   return TRUE;
 }
 
+static gboolean
+validate_boot_fd (OstreeSysroot *self, int fd, GError **error)
+{
+  g_assert_cmpint (fd, !=, -1);
+  struct statfs stbuf;
+  if (fstatfs (fd, &stbuf) < 0)
+    return glnx_throw_errno_prefix (error, "fstatfs(boot)");
+  self->boot_is_vfat = (stbuf.f_type == MSDOS_SUPER_MAGIC);
+  if (self->boot_is_vfat)
+    return glnx_throw (error, "/boot cannot currently be a vfat filesystem");
+  return TRUE;
+}
+
 /* Require that both self->sysroot_fd is set.
  * If the sysroot has a boot/ subdirectory, it will be loaded.
  * If not, self->boot_fd will remain -1.
@@ -352,14 +367,18 @@ _ostree_sysroot_maybe_load_boot_fd (OstreeSysroot *self, GError **error)
     return FALSE;
   if (self->boot_fd == -1)
     {
-      int fd = glnx_opendirat_with_errno (self->sysroot_fd, "boot", TRUE);
+      glnx_autofd int fd = glnx_opendirat_with_errno (self->sysroot_fd, "boot", TRUE);
       if (fd < 0)
         {
           if (errno != ENOENT)
             return glnx_throw_errno_prefix (error, "Opening boot/");
         }
       else
-        self->boot_fd = fd;
+        {
+          if (!validate_boot_fd (self, fd, error))
+            return FALSE;
+          self->boot_fd = glnx_steal_fd (&fd);
+        }
     }
   return TRUE;
 }
@@ -372,8 +391,12 @@ _ostree_sysroot_ensure_boot_fd (OstreeSysroot *self, GError **error)
     return FALSE;
   if (self->boot_fd == -1)
     {
-      if (!glnx_opendirat (self->sysroot_fd, "boot", TRUE, &self->boot_fd, error))
+      glnx_autofd int fd = -1;
+      if (!glnx_opendirat (self->sysroot_fd, "boot", TRUE, &fd, error))
+        return FALSE;
+      if (!validate_boot_fd (self, fd, error))
         return FALSE;
+      self->boot_fd = glnx_steal_fd (&fd);
     }
   return TRUE;
 }
diff --git a/tests/kolainst/nondestructive/itest-alt-sysroot.sh b/tests/kolainst/nondestructive/itest-alt-sysroot.sh
new file mode 100755 (executable)
index 0000000..eb6af64
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Run test-basic.sh as root.
+# https://github.com/ostreedev/ostree/pull/1199
+
+set -xeuo pipefail
+
+if test $(readlink /proc/1/ns/mnt) = $(readlink /proc/self/ns/mnt); then
+    exec unshare -m -- "$0" "$@"
+fi
+
+. ${KOLA_EXT_DATA}/libinsttest.sh
+
+# Use /var/tmp to hopefully use XFS + O_TMPFILE etc.
+prepare_tmpdir /var/tmp
+trap _tmpdir_cleanup EXIT
+
+truncate -s 512M boot.img
+mkfs.vfat boot.img
+
+mkdir sysroot
+ostree admin init-fs -E 1 sysroot
+mount -o loop boot.img sysroot/boot
+if ostree admin status --sysroot=sysroot 2>err.txt; then
+    # So cleanup works on failure too
+    umount sysroot/boot
+    fatal "computed status on vfat sysroot"
+fi
+umount sysroot/boot
+assert_file_has_content_literal err.txt "/boot cannot currently be a vfat filesystem"